﻿using System;
using System.Collections.Generic;
using UnityEngine;

public abstract class BaseFunctionalChessBoard : BaseChessBoard
{
    private int currentRoundIndex = 0;
    private bool isEnd = false;
    public List<((Pos, Pos), BaseChess)> record = new List<((Pos, Pos), BaseChess)>();
    private Pos unmeaningPos = new Pos(-1, -1);
    public int GetCurrentRoundIndex()
    {
        return currentRoundIndex;
    }
    public void ForceAddCurrentRoundIndex()
    {
        currentRoundIndex = (currentRoundIndex + 1) % fieldInfo.GetCampCount();
    }
    public void ForceSetCurrentRoundIndex(int index)
    {
        if (index < 0 || index > fieldInfo.GetCampCount())
        {
            throw new Exception();
        }
        currentRoundIndex = index;
    }
    public void ForceMove((Pos, Pos) path)
    {
        if (isEnd)
        {
            Debug.LogError("游戏结束");
            return;
        }
        BaseGrid grid = GetGridByPos(path.Item1);
        BaseChess moveChess = GetChessByGrid(grid);
        BaseGrid grid2 = GetGridByPos(path.Item2);
        BaseChess ateChess = GetChessByGrid(grid2);
        if (ateChess != null)
        {
            fieldInfo.ChessOff(ateChess, this);
            int campCount = fieldInfo.GetCampCount();
            bool judgeEnd = true;
            for (int i = 0; i < campCount; i++)
            {
                if (fieldInfo.GetTeamByCamp(i) != moveChess.GetTeam() && fieldInfo.GetCampScore(i).infCount > 0)
                {
                    judgeEnd = false;
                }
            }
            if (judgeEnd)
            {
                isEnd = true;
            }
        }
        fieldInfo.ChessMove(moveChess, path.Item2, this);
        ForceAddCurrentRoundIndex();
        record.Add((path, ateChess));
    }
    public bool TryMove((Pos, Pos) path)
    {
        BaseGrid grid = GetGridByPos(path.Item1);
        BaseChess moveChess = GetChessByGrid(grid);
        List<Pos> canMovePosList = new List<Pos>();
        moveChess.AddSomePosIntoList(this, canMovePosList);
        if (!canMovePosList.Contains(path.Item2) || moveChess.GetCamp() != currentRoundIndex)
        {
            Debug.LogWarning("不能移动到此点");
            return false;
        }
        else
        {
            ForceMove(path);
            return true;
        }
    }
    public void ForceNotMove()
    {
        ForceAddCurrentRoundIndex();
        record.Add(((unmeaningPos, unmeaningPos), null));
    }
    public void TryNotMove()
    {
        ForceNotMove();
    }
    //悔棋
    public bool Retract(int camp)
    {
        if (isEnd)
        {
            Debug.LogError("游戏结束，不给悔棋");
            return false;
        }
        if (camp + 1 > record.Count)
        {
            Debug.LogError("还没走第一步，不给悔棋");
            return false;
        }
        int stepCount;
        if (GetCurrentRoundIndex() == camp)
        {
            stepCount = GetCampCount();
        }
        else
        {
            stepCount = (GetCurrentRoundIndex() + GetCampCount() - camp) % GetCampCount();
        }
        for (int i = 0; i < stepCount; i++)
        {
            ((Pos, Pos), BaseChess) track = record[record.Count - 1];
            record.RemoveAt(record.Count - 1);
            if (track.Item1.Item1.Equals(unmeaningPos) || track.Item1.Item2.Equals(unmeaningPos))
            {
                continue;
            }
            BaseGrid grid = GetGridByPos(track.Item1.Item2);
            BaseChess moveChess = GetChessByGrid(grid);
            fieldInfo.ChessMove(moveChess, track.Item1.Item1, this);
            if (track.Item2 != null)
            {
                fieldInfo.ChessOn(track.Item2, track.Item1.Item2, this);
            }
        }
        ForceSetCurrentRoundIndex(camp);
        return true;
    }
    protected abstract BaseFunctionalChessBoard GetUninitializedInstance();
    //复制战场信息（不复制行棋记录）
    public BaseFunctionalChessBoard CloneBoard()
    {
        BaseFunctionalChessBoard cloneObj = GetUninitializedInstance();
        cloneObj.ForceSetCurrentRoundIndex(currentRoundIndex);
        List<(Pos, Type, int)> list = new List<(Pos, Type, int)>();
        for (int i = 0; i < fieldInfo.GetCampCount(); i++)
        {
            HashSet<BaseChess> set = fieldInfo.DirectGetOnlineChessSetByCamp(i);
            foreach (BaseChess chess in set)
            {
                list.Add((fieldInfo.GetGridByChess(chess).GetPos(), chess.GetType(), i));
            }
        }
        cloneObj.fieldInfo.Init(list, cloneObj);
        return cloneObj;
    }
    public bool IsEnd()
    {
        return isEnd;
    }
}